/******************************************************************************
 * @file     main.h
 * @brief    Bootloader主函数文件
 * @author   Ruilist
 * @date     2025-08-15
 * @version  V1.0.0
 * @copyright Copyright (c) 2025
 *
 * @note     1 tab = 4 space
 *
 * @par 日志:
 * - V1.0.0 2025-08-15 Ruilist
 *****************************************************************************/

//******************************** Includes *********************************//

#include "main.h"

#include "usart.h"
#include "gpio.h"
#include "flash.h"
#include "Debug.h"
#include "elog.h"
#include "Boot_Manager.h"
#include "Ymodem.h"
#include "spi.h"
#include "w25qxx_handler.h"
#include "AT24Cxx_Driver.h"

//******************************** Includes *********************************//

//******************************** Defines **********************************//

static __IO uint32_t uwTimingDelay;
RCC_ClocksTypeDef    RCC_Clocks;

//******************************** Defines **********************************//

//******************************** Declaring ********************************//

/**
 * @brief  Main program
 * @param  None
 * @retval None
 */
int main( void )
{
    RCC_ClockSecuritySystemCmd( ENABLE );

    SystemCoreClockUpdate();
    RCC_GetClocksFreq( &RCC_Clocks );
    SysTick_Config( RCC_Clocks.HCLK_Frequency / 1000 );

    gpio_init();
    // TIM_Config();
    USART1_Init();

    bootloader_elog_init();

    SPI1_Init();
    ee_CheckOk();  // AT24C02初始化
    W25Q64_Init();

    log_i( "bootloader start\r\n" );

    OTA_state_manager();

    while ( 1 )
    {
        log_w( "no available app!" );
        while ( 1 )
        {
            int32_t file_size = 0;  // 固件大小
            // uint32_t app_size  = 0;  // app大小

            if ( Key_Scan() )
            {
                file_size = Ymodem_Receive( Ymodem_rec );
                // 对固件解密，解密后存放在B区
                if ( 0 == ExA_To_ExB_AES( file_size ) )
                {
                    // ee_ReadBytes( (uint8_t *)&app_size, 0x05, 4 );  // 读当前App的大小
                    // log_d( "ee_ReadBytes ok appsize is[%x]\r\n", app_size );
                    // App_To_ExA( app_size );
                    // 复制flashB中的数据到rom中
                    ExB_To_App();
                    JumpToApp();
                }
                else
                {
                    // 解密错误
                    log_w( "Boot dowload failed" );
                    JumpToApp();
                }
            }
            Delay( 500 );
            GPIO_SetBits( LED_C13_PORT, LED_C13_PIN );
            Delay( 500 );
            GPIO_ResetBits( LED_C13_PORT, LED_C13_PIN );
        }
    }
}
/**
 * @brief  Inserts a delay time.
 * @param  nTime: specifies the delay time length, in milliseconds.
 * @retval None
 */
void Delay( __IO uint32_t nTime )
{
    uwTimingDelay = nTime;

    while ( uwTimingDelay != 0 )
        ;
}

/**
 * @brief  Decrements the TimingDelay variable.
 * @param  None
 * @retval None
 */
void TimingDelay_Decrement( void )
{
    if ( uwTimingDelay != 0x00 )
    {
        uwTimingDelay--;
    }
}

#ifdef USE_FULL_ASSERT

/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed( uint8_t *file, uint32_t line )
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while ( 1 )
    {
    }
}
#endif

//******************************** Declaring ********************************//
